import java.util.ArrayList;
/**
 * An object of type StatsList stores a Stats and a list of Stats corresponding to
 * the stats for a game with a specific min and max value.
 *
 */
public class StatsList 
{
	private Stats baseStats;
	private ArrayList<GameTypeNode> list;
	
	public StatsList()
	{
		baseStats= new Stats();
		list= new ArrayList<GameTypeNode>();
	}
	
	/**
	 * Creates a StatsList using the stats derived from a SubitizePanel.
	 * 
	 * @param source the SubitizePanel to derive stats from.
	 */
	public StatsList(SubitizePanel source)
	{
		baseStats= new Stats(source);
		list= new ArrayList<GameTypeNode>();
		addGameTypeNode(source);
	}
	
	/**
	 * Adds the stats from a SubitizePanel to the Stats and the list of Stats
	 *  
	 * @param addition
	 */
	public void addGame(SubitizePanel addition)
	{
		baseStats.addGame(addition);
		addGameTypeNode(addition);
	}
	
	public Stats getBaseStats() 
	{
		return baseStats;
	}
	
	public ArrayList<GameTypeNode> getList()
	{
		return list;
	}
	
	public Stats getStats(int minValue, int maxValue)
	{
		for(GameTypeNode k : list)
		{
			if(k.maxValue==maxValue&&
			   k.minValue==minValue)
			{
				return k.game;
			}
		}
		return null;
	}
	
	
	/**
	 * Adds a SubitizePanel's stats to the list
	 * 
	 * @param addition
	 */
	private void addGameTypeNode(SubitizePanel addition)
	{
		for(GameTypeNode k : list)
		{
			if(k.maxValue==addition.getMaxNumberOfCircles()&&
			   k.minValue==addition.getMinNumberOfCircles())
			{
				k.game.addGame(addition);
				return;
			}
		}
		list.add(new GameTypeNode(addition));
	}
	
	public static StatsList singleEntryList(Stats addition, int minValue, int maxValue)
	{
		StatsList temp= new StatsList();
		temp.baseStats= addition;
		temp.list.add(new GameTypeNode(minValue, maxValue, addition));
		return temp;
	}
	
	/**
	 * Returns a String Representation of this StatsList
	 */
	@Override
	public String toString()
	{
		String baseString= baseStats.toString();
		String nodeString= "";
		for(GameTypeNode runner : list)
		{
			nodeString+= runner.maxValue+"c"+runner.minValue+"c"+runner.toString();
		}
		return baseString+nodeString+"f";
	}
	
	/**
	 * Reverses toString will create a new StatsList form a string.
	 * will throw an IllegalArgumentException if it can't parse the String.
	 * 
	 * @param source the string representation.
	 * @return the new StatsList
	 */
	public static StatsList fromString(String source)
	{
		char[] chars= source.toCharArray();
		String next= "";
		int nextMax= 0;
		int nextMin= 0;
		Stats nextGame;
		boolean foundBase= false;
		boolean foundMax= false;
		boolean foundMin= false;
		StatsList temp= new StatsList();
		
		for(int k=0; k<chars.length; k++)
		{
			if(chars[k]=='f') break;
			else if(foundBase==false)
			{
				if(chars[k]=='d')
				{
					temp.baseStats= Stats.fromString(next);
					next= "";
					foundBase= true;
				}
				else next+= chars[k];
			}
			else if(foundMax==false)
			{
				if(chars[k]=='c')
				{
					nextMax= Integer.parseInt(next);
					next= "";
					foundMax= true;
				}
				else next+= chars[k]; 
			}
			else if(foundMin==false)
			{
				if(chars[k]=='c')
				{
					nextMin= Integer.parseInt(next);
					next= "";
					foundMin= true;
				}
				else next+= chars[k]; 
			}
			else
			{
				if(chars[k]=='d')
				{
					nextGame= Stats.fromString(next);
					next= "";
					foundMax= false;
					foundMin= false;
					temp.list.add(new GameTypeNode(nextMin, nextMax, nextGame));
				}
				else next+= chars[k];
			}
		}
		return temp;
	}
	
	/**
	 * A node in the list stores a Stats and it's min and max values
	 *
	 */
	public static class GameTypeNode
	{
		private int minValue;
		private int maxValue;
		private Stats game;
		
		private GameTypeNode(int minValue, int maxValue, Stats game) 
		{
			this.minValue= minValue;
			this.maxValue= maxValue;
			this.game= game;
		}
		
		private GameTypeNode(SubitizePanel panel) 
		{
			minValue= panel.getMinNumberOfCircles();
			maxValue= panel.getMaxNumberOfCircles();
			game= new Stats(panel);
		}
		
		public int getMinValue()
		{
			return minValue;
		}
		
		public int getMaxValue()
		{
			return maxValue;
		}
		
		
		public Stats getGame()
		{
			return game;
		}
		@Override
		public String toString()
		{
			return game.toString();
		}
	}
}
